from rest_framework.generics import ListAPIView, CreateAPIView, UpdateAPIView
from api import models
from api.serializer.order import OrderModelSerializer, CouponModelSerializer, UserCouponModelSerializer, \
    MyUserCouponModelSerializer, AddressModelSerializer
from collections import OrderedDict
from api.authentication.auth import UserAuthentication
from django.http import JsonResponse
from api.web.web_Form.CouponMoldeForm import CouponMoldeForm
from api import task
import datetime
import json
from celery.result import AsyncResult
from auction import celery_app
from django.views.decorators.csrf import csrf_exempt
from django.db import transaction
from rest_framework import exceptions
from rest_framework import status


class OrderView(ListAPIView):
    queryset = models.Order.objects
    serializer_class = OrderModelSerializer
    authentication_classes = [UserAuthentication]

    def get_queryset(self):
        return self.queryset.filter(user=self.request.user)

    def list(self, request, *args, **kwargs):
        response = super().list(request, *args, **kwargs)

        order_list = OrderedDict()
        order_status_list = {'1': '未支付', '2': '待收货', '3': '已完成', '4': '逾期未支付'}
        for order_status in order_status_list.items():
            order_list[order_status[0]] = {"text": order_status[1]}
            order_list[order_status[0]]['child'] = []
        for row in response.data:
            order_list[str(row['status'])]['child'].append(row)
        response.data = order_list.values()
        return response


class CouponView(ListAPIView, CreateAPIView):
    queryset = models.Coupon.objects
    serializer_class = CouponModelSerializer

    def get_queryset(self):
        pk = self.kwargs.get('pk')
        if not pk:
            return self.queryset.filter(deleted=False, status__gt=1)
        return self.queryset.filter(deleted=False, auction_id=pk)

    def perform_create(self, serializer):
        pk = self.kwargs.get('pk')
        instance = serializer.save(auction_id=pk)
        # 1.定时任务,从 未开始 到领取中
        start_apply_datetime = datetime.datetime.utcfromtimestamp(serializer.instance.apply_start_date.timestamp())
        start_task_id = task.coupon_start_apply.apply_async(args=[instance.id], eta=start_apply_datetime).id

        # 2.定时任务,从 领取中 到已结束
        stop_apply_datetime = datetime.datetime.utcfromtimestamp(serializer.instance.apply_stop_date.timestamp())
        stop_task_id = task.coupon_stop_apply.apply_async(args=[instance.id], eta=stop_apply_datetime).id
        instance.apply_start_task_id = start_task_id
        instance.apply_stop_task_id = stop_task_id
        instance.save()


class UserCouponView(ListAPIView, CreateAPIView):
    authentication_classes = [UserAuthentication]

    def perform_create(self, serializer):
        with transaction.atomic():
            # 查询优惠卷对象
            coupon_object = models.Coupon.objects.filter(
                id=serializer.validated_data['coupon'].id).select_for_update().first()
            # 判断优惠卷是否被领完
            if (coupon_object.apply_count + 1) > coupon_object.count:
                raise exceptions.ValidationError('优惠券已领完')
            serializer.save(user=self.request.user)
            coupon_object.apply_count += 1
            coupon_object.save()

    def get_serializer_class(self):
        if self.request.method == 'POST':
            return UserCouponModelSerializer
        return MyUserCouponModelSerializer

    def get_queryset(self):
        return models.UserCoupon.objects.filter(user=self.request.user)

    def list(self, *args, **kwargs):
        response = super().list(*args, **kwargs)  # [{},{},{}]
        if response.status_code != status.HTTP_200_OK:
            return response
        status_dict = OrderedDict()
        for item in models.UserCoupon.status_choices:
            status_dict[item[0]] = {'text': item[1], 'child': []}

        for row in response.data:
            status_dict[row['status']]['child'].append(row)

        response.data = status_dict
        return response


# 第二种修改方法
class CouponEditView(UpdateAPIView):
    queryset = models.Coupon.objects
    serializer_class = CouponModelSerializer

    def get_queryset(self):
        pk = self.kwargs.get('pk')
        return self.queryset.filter(deleted=False, id=pk)

    def perform_update(self, serializer):
        coupon_object = self.request.data
        if "apply_start_date" in serializer.validated_data:
            async_result = AsyncResult(id=coupon_object.get('apply_start_task_id'), app=celery_app)
            async_result.revoke()
            eta = datetime.datetime.utcfromtimestamp(serializer.instance.apply_start_date.timestamp())
            start_task_id = task.coupon_start_apply.apply_async(args=[coupon_object.get('id')], eta=eta).id
            serializer.instance.apply_start_task_id = start_task_id

        if "apply_stop_date" in serializer.validated_data:
            async_result = AsyncResult(id=coupon_object.get('apply_stop_task_id'), app=celery_app)
            async_result.revoke()
            eta = datetime.datetime.utcfromtimestamp(serializer.instance.apply_stop_date.timestamp())
            start_task_id = task.coupon_stop_apply.apply_async(args=[coupon_object.get('id')], eta=eta).id
            serializer.instance.apply_start_task_id = start_task_id
        serializer.save()


class AddressView(ListAPIView, CreateAPIView):
    authentication_classes = [UserAuthentication, ]
    serializer_class = AddressModelSerializer

    def get_queryset(self):
        return models.Address.objects.filter(user=self.request.user).order_by('-id')

    def perform_create(self, serializer):
        serializer.save(user=self.request.user)


def CouponDelete(request, pk):
    coupon_object = models.Coupon.objects.filter(deleted=False, id=pk).first()
    if not coupon_object:
        return JsonResponse({'status': False, 'error': '优惠卷不存在'})
    # 关闭定时任务
    start_result = AsyncResult(id=coupon_object.apply_start_task_id, app=celery_app)
    start_result.revoke()

    stop_result = AsyncResult(id=coupon_object.apply_stop_task_id, app=celery_app)
    stop_result.revoke()
    models.Coupon.objects.filter(deleted=False, id=pk).update(deleted=True)
    return JsonResponse({"status": True})


# 第一种修改方法
@csrf_exempt
def CouponEdit(request, pk):
    if request.method == "POST":
        coupon_list = json.loads(request.body.decode('utf8')).get('coupon')

        coupon_object = models.Coupon.objects.filter(id=pk, deleted=False).first()
        if coupon_object.status != 1:
            return JsonResponse({'status': False, 'message': "修改优惠卷时间已过"})

        form = CouponMoldeForm(data=coupon_list, instance=coupon_object)
        print(form.errors.get_json_data())
        if form.is_valid():
            # 判断时间是否修改
            if "apply_start_date" in form.changed_data:
                async_result = AsyncResult(id=coupon_object.apply_start_task_id, app=celery_app)
                async_result.revoke()
                eta = datetime.datetime.utcfromtimestamp(form.instance.apply_start_date.timestamp())
                start_task_id = task.coupon_start_apply.apply_async(args=[coupon_object.id], eta=eta).id
                form.instance.apply_start_task_id = start_task_id

            if "apply_stop_date" in form.changed_data:
                async_result = AsyncResult(id=coupon_object.apply_stop_task_id, app=celery_app)
                async_result.revoke()
                eta = datetime.datetime.utcfromtimestamp(form.instance.apply_stop_date.timestamp())
                start_task_id = task.coupon_stop_apply.apply_async(args=[coupon_object.id], eta=eta).id
                form.instance.apply_start_task_id = start_task_id
            form.save()
            return JsonResponse({'status': True})
    return JsonResponse({'status': False, 'message': "数据有误"})
